package com.copd.service.impl;

import com.copd.service.DataRestoreService;
import com.copd.service.DoctorOperationLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class DataRestoreServiceImpl implements DataRestoreService {
    
    private static final Logger logger = LoggerFactory.getLogger(DataRestoreServiceImpl.class);
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private DoctorOperationLogService logService;
    
    // 表名映射 - 原表名 -> 备份表名
    private static final Map<String, String> tableNameMapping;
    
    // 表字段映射 - 表名 -> 字段列表
    private static final Map<String, List<String>> tableFieldsMapping;
    
    static {
        // 初始化表名映射
        Map<String, String> tableMap = new HashMap<>();
        tableMap.put("patient_info", "patient_info_backup");
        tableMap.put("diagnosis_records", "diagnosis_records_backup");
        tableMap.put("examination_items", "examination_items_backup");
        tableMap.put("treatment_plans", "treatment_plans_backup");
        tableMap.put("discharge_records", "discharge_records_backup");
        tableNameMapping = Collections.unmodifiableMap(tableMap);
        
        // 初始化字段映射
        Map<String, List<String>> fieldsMap = new HashMap<>();
        
        // 患者基本信息表字段
        fieldsMap.put("patient_info", Arrays.asList(
            "user_id", "patient_id", "name", "gender", "age", 
            "department", "hospitalization_number"
        ));
        
        // 诊断记录表字段
        fieldsMap.put("diagnosis_records", Arrays.asList(
            "record_id", "patient_id", "diagnosis_item", "diagnosis_content", 
            "remarks", "diagnosis_date"
        ));
        
        // 检查项目表字段
        fieldsMap.put("examination_items", Arrays.asList(
            "exam_id", "patient_id", "exam_category", "exam_item", 
            "exam_result", "reference_value", "remarks", "exam_date"
        ));
        
        // 治疗计划表字段
        fieldsMap.put("treatment_plans", Arrays.asList(
            "plan_id", "patient_id", "plan_category", "treatment_item", 
            "specific_plan", "remarks", "plan_date"
        ));
        
        // 出院建议表字段
        fieldsMap.put("discharge_records", Arrays.asList(
            "discharge_id", "patient_id", "advice_category", "discharge_item", 
            "discharge_content", "remarks", "advice_date"
        ));
        
        tableFieldsMapping = Collections.unmodifiableMap(fieldsMap);
    }

    @Override
    @Transactional
    public Map<String, Object> restorePatientData(Integer patientId, Integer doctorId, List<String> tables) {
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> tableResults = new HashMap<>();
        
        if (patientId == null || doctorId == null || tables == null || tables.isEmpty()) {
            result.put("success", false);
            result.put("message", "患者ID、医生ID和表名不能为空");
            return result;
        }
        
        try {
            // 验证请求的有效性
            Map<String, Object> validationResult = validateRestoreRequest(patientId, doctorId, tables);
            if (!(boolean) validationResult.get("valid")) {
                result.put("success", false);
                result.put("message", validationResult.get("message"));
                return result;
            }
            
            // 遍历每个表执行恢复操作
            for (String tableName : tables) {
                // 处理带有_backup后缀的表名
                String originalTableName;
                if (tableName.endsWith("_backup")) {
                    originalTableName = tableName.substring(0, tableName.length() - "_backup".length());
                    if (!tableFieldsMapping.containsKey(originalTableName)) {
                        tableResults.put(tableName, "不支持的表名");
                        continue;
                    }
                } else {
                    if (!tableNameMapping.containsKey(tableName)) {
                        tableResults.put(tableName, "不支持的表名");
                        continue;
                    }
                    originalTableName = tableName;
                }
                
                boolean restored = restoreTable(originalTableName, tableName, patientId, doctorId);
                tableResults.put(tableName, restored ? "恢复成功" : "恢复失败");
            }
            
            // 记录操作日志
            logService.logPatientOperation(
                doctorId,
                patientId,
                "恢复",
                "0:0:0:0:0:0:0:1", // IP地址，实际应从请求中获取
                "系统操作", // User-Agent，实际应从请求中获取
                true,
                null,
                "backup_data",
                patientId,
                "从备份中恢复患者 " + patientId + " 的数据，恢复表: " + String.join(", ", tables)
            );
            
            result.put("success", true);
            result.put("message", "数据恢复操作已完成");
            result.put("details", tableResults);
            
            return result;
        } catch (Exception e) {
            logger.error("恢复患者数据时发生错误", e);
            // 由于有@Transactional注解，错误会自动回滚事务
            
            result.put("success", false);
            result.put("message", "恢复数据时发生错误: " + e.getMessage());
            return result;
        }
    }
    
    @Override
    public Map<String, Object> validateRestoreRequest(Integer patientId, Integer doctorId, List<String> tables) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 检查患者是否存在
            String checkPatientSql = "SELECT COUNT(*) FROM patient_info WHERE patient_id = ?";
            Integer patientCount = jdbcTemplate.queryForObject(checkPatientSql, Integer.class, patientId);
            
            // 检查医生是否存在
            String checkDoctorSql = "SELECT COUNT(*) FROM Users WHERE user_id = ?";
            Integer doctorCount = jdbcTemplate.queryForObject(checkDoctorSql, Integer.class, doctorId);
            
            // 检查备份数据是否存在
            boolean hasBackupData = false;
            for (String tableName : tables) {
                // 如果表名已经带有_backup后缀，直接使用该表名作为备份表名
                String backupTableName;
                if (tableName.endsWith("_backup")) {
                    backupTableName = tableName;
                    // 从原表映射中查找是否支持该表（去掉_backup后缀后的原表名）
                    String originalTableName = tableName.substring(0, tableName.length() - "_backup".length());
                    if (!tableFieldsMapping.containsKey(originalTableName)) {
                        logger.warn("不支持的表名: {}", tableName);
                        continue;
                    }
                } else {
                    // 原始逻辑，如果表名不带后缀，使用映射来查找备份表名
                    if (!tableNameMapping.containsKey(tableName)) {
                        logger.warn("不支持的表名: {}", tableName);
                        continue;
                    }
                    backupTableName = tableNameMapping.get(tableName);
                }
                
                String checkBackupSql = "SELECT COUNT(*) FROM " + backupTableName + " WHERE patient_id = ?";
                Integer backupCount;
                try {
                    backupCount = jdbcTemplate.queryForObject(checkBackupSql, Integer.class, patientId);
                } catch (Exception e) {
                    logger.error("查询备份表 {} 时出错: {}", backupTableName, e.getMessage());
                    continue;
                }
                
                if (backupCount != null && backupCount > 0) {
                    hasBackupData = true;
                    break;
                }
            }
            
            // 验证结果
            if (patientCount == null || patientCount == 0) {
                result.put("valid", false);
                result.put("message", "患者ID不存在: " + patientId);
            } else if (doctorCount == null || doctorCount == 0) {
                result.put("valid", false);
                result.put("message", "医生ID不存在: " + doctorId);
            } else if (!hasBackupData) {
                result.put("valid", false);
                result.put("message", "未找到该患者的备份数据");
            } else {
                result.put("valid", true);
                result.put("message", "验证通过");
            }
        } catch (Exception e) {
            logger.error("验证恢复请求时发生错误", e);
            result.put("valid", false);
            result.put("message", "验证请求时发生错误: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 恢复单个表的数据
     * 
     * @param originalTableName 原表名（不带后缀）
     * @param backupTableFullName 备份表名（完整的，可能带有_backup后缀）
     * @param patientId 患者ID
     * @param doctorId 医生ID
     * @return 是否恢复成功
     */
    private boolean restoreTable(String originalTableName, String backupTableFullName, Integer patientId, Integer doctorId) {
        try {
            // 确定备份表名
            String backupTableName;
            if (backupTableFullName.endsWith("_backup")) {
                backupTableName = backupTableFullName;
            } else {
                backupTableName = tableNameMapping.get(backupTableFullName);
            }
            
            List<String> fields = tableFieldsMapping.get(originalTableName);
            
            if (fields == null || fields.isEmpty()) {
                logger.error("没有为表 {} 定义字段列表", originalTableName);
                return false;
            }
            
            // 构建字段列表字符串
            String fieldsStr = String.join(", ", fields);
            
            // 检查备份表中是否有数据
            String checkBackupSql = "SELECT COUNT(*) FROM " + backupTableName + " WHERE patient_id = ?";
            Integer backupCount;
            try {
                backupCount = jdbcTemplate.queryForObject(checkBackupSql, Integer.class, patientId);
            } catch (Exception e) {
                logger.error("查询备份表 {} 时出错: {}", backupTableName, e.getMessage());
                return false;
            }
            
            if (backupCount == null || backupCount == 0) {
                logger.warn("备份表 {} 中没有患者 {} 的数据", backupTableName, patientId);
                return false;
            }
            
            // 1. 先删除原表中的数据
            String deleteSql = "DELETE FROM " + originalTableName + " WHERE patient_id = ?";
            int deletedRows = jdbcTemplate.update(deleteSql, patientId);
            logger.info("从表 {} 中删除了 {} 行患者 {} 的数据", originalTableName, deletedRows, patientId);
            
            // 2. 从备份表中查询数据
            String selectSql = "SELECT " + fieldsStr + " FROM " + backupTableName + " WHERE patient_id = ?";
            List<Map<String, Object>> backupData;
            try {
                backupData = jdbcTemplate.queryForList(selectSql, patientId);
            } catch (Exception e) {
                logger.error("从备份表 {} 查询数据时出错: {}", backupTableName, e.getMessage());
                return false;
            }
            
            if (backupData.isEmpty()) {
                logger.warn("备份表 {} 中没有查询到患者 {} 的数据", backupTableName, patientId);
                return false;
            }
            
            // 3. 插入数据到原表
            // 构建占位符字符串 ?, ?, ?...
            String placeholders = String.join(", ", Collections.nCopies(fields.size(), "?"));
            
            String insertSql = "INSERT INTO " + originalTableName + " (" + fieldsStr + ") VALUES (" + placeholders + ")";
            
            // 逐条插入数据
            int insertedRows = 0;
            for (Map<String, Object> row : backupData) {
                Object[] params = new Object[fields.size()];
                for (int i = 0; i < fields.size(); i++) {
                    params[i] = row.get(fields.get(i));
                }
                
                jdbcTemplate.update(insertSql, params);
                insertedRows++;
            }
            
            logger.info("向表 {} 中插入了 {} 行患者 {} 的数据", originalTableName, insertedRows, patientId);
            
            return true;
        } catch (DataAccessException e) {
            logger.error("恢复表 {} 中患者 {} 的数据时发生错误", originalTableName, patientId, e);
            throw e; // 重新抛出异常，让事务管理器处理
        }
    }

    /**
     * 兼容旧签名，保持向后兼容性
     */
    private boolean restoreTable(String tableName, Integer patientId, Integer doctorId) {
        return restoreTable(tableName, tableName, patientId, doctorId);
    }
} 